/*
 * SamplePlugin.SamplePlugin
 * Andy Tidball
 * 
 * Project: Black Lightning Sample Plugin
 * Copyright: GNU General Public License
 */

using System;
using System.Text.RegularExpressions;
using BlackLightning.PluginLib;
using BlackLightning.PluginLib.Modules;
using BlackLightning.PluginLib.Modules.Packets;

[assembly: Author("Andy Tidball")]
[assembly: WebSite("http://www.blacklightning.net")]
[assembly: BLVersion("0.8.3.100")]

// this attribute, like the BLModule attribute, tells the assembly as a whole which object represents the plugin itself
// unlike the BLModule attribute, each assembly can only have a single BLPlugin attribute
[assembly: BLPlugin(typeof(SamplePlugin.SamplePlugin))]

namespace SamplePlugin {
	/// <summary>
	/// A sample plugin which displays messages when it is loaded and unloaded.
	/// </summary>
	class SamplePlugin : IPlugin {
		// constants
		private const string HelpText                     = @"This plugin contains the Echo module.";

		// constants - "Echo Packets" option setup
		private const string EchoPacketsOptionName        = "Echo Packets";
		private const string EchoPacketsOptionDescription = "If turned on then all packets sent to modules in this plugin will be echoed to the front end.";
		private const bool   EchoPacketsOptionDefault     = false;

		// member data
		private bool _EchoPackets = EchoPacketsOptionDefault; // whether or not we want to echo packets going to our modules or not

		/// <summary>
		/// We can fire this event to send a private message to Black Lightning.
		/// </summary>
		public event SendMessageEventHandler SendMessage;

		/// <summary>
		/// We can fire this event to send a packet to Black Lightning for routing to other modules and possibly another program.
		/// </summary>
		public event SendPacketEventHandler SendPacket;

		/// <summary>
		/// Gets a property of the plugin.
		/// </summary>
		/// <param name="Property">The property of the plugin that Black Lightning is requesting.</param>
		/// <returns>The value of the requested property, or null if this plugin doesn't use that property.</returns>
		public object GetProperty(PluginProperty Property) {
			switch (Property) {
				case PluginProperty.HelpText:             return HelpText;
				case PluginProperty.ReceiveModulePackets: return _EchoPackets;
				default:                                  return null;
			}
		}

		/// <summary>
		/// Called by Black Lightning whenever it has a private message for us.
		/// </summary>
		/// <param name="Message">The private message that Black Lightning is sending to us.</param>
		public void HandleMessage(Message Message) {
			if (Message is LoadedMessage) {
				// this message is sent to us when we are first loaded
				HandleMessage_Loaded(Message as LoadedMessage);
			} else if (Message is UnloadedMessage) {
				// this message is sent to us when we're about to be unloaded
				HandleMessage_Unloaded(Message as UnloadedMessage);
			} else if (Message is OptionValueChangedMessage) {
				// this message is sent when our option value changes
				HandleMessage_OptionValueChanged(Message as OptionValueChangedMessage);
			}
		}

		/// <summary>
		/// Handles all LoadedMessages sent to us.
		/// </summary>
		/// <param name="Message">The LoadedMessage sent to us by Black Lightning.</param>
		private void HandleMessage_Loaded(LoadedMessage Message) {
			// register for @echo-on and @echo-off commands
			SendMessage(this, new SendMessageEventArgs(new RegisterPacketMessage(new CommandPacketFilter(Program.FrontEnd, Program.BlackLightning, "@echo-on"))));
			SendMessage(this, new SendMessageEventArgs(new RegisterPacketMessage(new CommandPacketFilter(Program.FrontEnd, Program.BlackLightning, "@echo-off"))));

			// register our Echo Packets option
			SendMessage(this, new SendMessageEventArgs(new RegisterOptionMessage(EchoPacketsOptionName, EchoPacketsOptionDefault.GetType(), EchoPacketsOptionDefault, EchoPacketsOptionDescription)));

			// send a welcome message to the front end
			SendPacket(this, new SendPacketEventArgs(new RawBLPacket(Program.BlackLightning, Program.FrontEnd, "Welcome to the Sample Plugin.")));
		}

		/// <summary>
		/// Handles all UnloadedMessages sent to us.
		/// </summary>
		/// <param name="Message">The UnloadedMessage sent to us by Black Lightning.</param>
		private void HandleMessage_Unloaded(UnloadedMessage Message) {
			// send a farewell message to the front end
			SendPacket(this, new SendPacketEventArgs(new RawBLPacket(Program.BlackLightning, Program.FrontEnd, "Thanks for using the Sample Plugin.")));
		}

		/// <summary>
		/// Handles all OptionValueChangedMessages sent to us.
		/// </summary>
		/// <param name="Message">The OptionValueChangedMessage sent to us by Black Lightning.</param>
		private void HandleMessage_OptionValueChanged(OptionValueChangedMessage Message) {
			// we only registered one option so this isn't really necessary
			// however, with more than one option you'd need to check the name to see which one changed
			if (Message.Name == EchoPacketsOptionName) {
				// store the new value
				_EchoPackets = (bool)Message.NewValue;
			}
		}

		/// <summary>
		/// Called by Black Lightning whenever it has a packet for us to process.
		/// </summary>
		/// <param name="Packet">The packet that we should handle.</param>
		public void HandlePacket(ref BLPacket Packet) {
			// we know this is a command packet because that's all we registered for
			CommandPacket P = Packet as CommandPacket;

			// check if this is an echo-on or echo-off command
			if (P.Command == "@echo-on") {
				// tell Black Lightning to change the value of our option
				SendMessage(this, new SendMessageEventArgs(new ChangeOptionValueMessage(EchoPacketsOptionName, true)));

				// let the user know that it was changed
				SendPacket(this, new SendPacketEventArgs(new RawBLPacket(Program.BlackLightning, Program.FrontEnd, "Echo all turned on.")));

				// suppress the packet and return
				P.Suppress();
				return;
			} else if (P.Command == "@echo-off") {
				// tell Black Lightning to change the value of our option
				SendMessage(this, new SendMessageEventArgs(new ChangeOptionValueMessage(EchoPacketsOptionName, false)));

				// let the user know it was changed
				SendPacket(this, new SendPacketEventArgs(new RawBLPacket(Program.BlackLightning, Program.FrontEnd, "Echo all turned off.")));

				// suppress the packet and return
				P.Suppress();
				return;
			}

			// join the command to the arguments to send back to the front end
			string Data = P.Command + " " + string.Join(" ", P.Arguments);

			// echo the packet's data to the front end
			// (we would only receive other packets if our ReceiveModulePackets is currently returning true)
			SendPacket(this, new SendPacketEventArgs(new RawBLPacket(Program.BlackLightning, Program.FrontEnd, Data)));
		}
	}
}
